package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.album.config.MinioConstantProperties;
import com.atguigu.tingshu.album.service.AuditService;
import com.atguigu.tingshu.album.service.FileUpLoadService;
import com.atguigu.tingshu.common.execption.GuiguException;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

@Service
public class FileUpLoadServiceImpl implements FileUpLoadService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConstantProperties minioConstantProperties;

    @Autowired
    private AuditService auditService;



    /***
     * 图片(封面, 头像) 文件上传
     * @param multipartFile
     * @return
     */
    @Override
    public String fileUpload(MultipartFile multipartFile) {
        BufferedImage processedImage;
        String contentType = multipartFile.getContentType();
        try {
            BufferedImage bufferedImage = ImageIO.read(multipartFile.getInputStream());

            if (bufferedImage == null) {
                throw new GuiguException(400, "文件格式不正确");
            }
            // 获取原图的宽度和高度
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();

            if (width > 900 || height > 900) {
                processedImage = validateAndResizeImage(bufferedImage);
            } else {
                processedImage = bufferedImage;
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            // 创建以当前日期命名的文件夹路径，格式为"/yyyy-MM-dd"
            String folder = "/" + DateUtil.today();
            // 生成一个随机的UUID作为文件名，避免文件名冲突
            String filename = IdUtil.randomUUID();
            // 获取上传文件的原始文件名中的扩展名（如.jpg/.png等）
            String extedName = FileNameUtil.extName(multipartFile.getOriginalFilename());
            String objname = folder + "/" + filename + "." + extedName;

            // 将BufferedImage转换为字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            String formatName = extedName.toLowerCase();
            // 确保格式名称正确
            if (formatName.equals("jpg")) {
                formatName = "jpeg";
            }
            ImageIO.write(processedImage, formatName, baos);
            byte[] imageBytes = baos.toByteArray();
            baos.close();

            // 调用minio客户端上传处理后的图片
            String bucketName = minioConstantProperties.getBucketName();

            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objname)
                    .stream(new ByteArrayInputStream(imageBytes), imageBytes.length, -1)
                    .contentType(contentType)
                    .build()
            );
            return minioConstantProperties.getEndpointUrl() + "/" + bucketName + "/" + objname;
        } catch (Exception e) {
            System.out.println("e是:"+e.getMessage());
            throw new GuiguException(500, "文件上传失败");
        }
    }


    /**
     * 图片尺寸校验和等比例缩放方法
     * 如果图片尺寸在900像素以内，返回原图；如果超过900像素，将长的一边按等比例缩放到900像素以内
     *
     * @param originalImage 原始图片的BufferedImage对象
     * @return 处理后的BufferedImage对象（原图或缩放后的图片）
     */
    public static BufferedImage validateAndResizeImage(BufferedImage originalImage) {

        // 获取原图的宽度和高度
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        // 计算缩放比例：取宽度缩放比和高度缩放比中的较小值，确保等比例缩放且最大边不超过900
        // Math.min确保长边会被缩放到900以内，短边按相同比例缩放
        double scale = Math.min(900.0 / width, 900.0 / height);

        // 根据缩放比例计算新的宽高
        int newWidth = (int) (width * scale);   // 缩放后的宽度
        int newHeight = (int) (height * scale); // 缩放后的高度

        // 创建新的BufferedImage对象，用于存储缩放后的图片
        // 保持原图的颜色类型(getType())
        BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, originalImage.getType());

        // 获取Graphics2D对象用于绘制缩放后的图片
        Graphics2D g2d = scaledImage.createGraphics();

        // 设置图片缩放时的插值方式为双线性插值，提高缩放后图片质量
        // VALUE_INTERPOLATION_BILINEAR可以让缩放后的图片更平滑
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

        // 将原图按新尺寸绘制到新的BufferedImage上
        // 参数：原图, 目标x坐标, 目标y坐标, 目标宽度, 目标高度, ImageObserver
        g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null);

        // 释放Graphics2D资源
        g2d.dispose();

        // 返回缩放后的图片
        return scaledImage;
    }
}
